package org.jsola.hr.service.impl;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.RowBounds;
import org.jsola.admin.entity.SiteDO;
import org.jsola.approval.dto.IssuedApproFlowAddDTO;
import org.jsola.approval.vo.ApproFlowListVO;
import org.jsola.common.StrKit;
import org.jsola.contract.dto.IssuedCategoryAddDTO;
import org.jsola.contract.entity.CategoryDO;
import org.jsola.contract.entity.SealDO;
import org.jsola.core.Page;
import org.jsola.core.entity.BaseDO;
import org.jsola.core.entity.BaseTreeDO;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.DateUtils;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.HrLogKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.ICompanyDAO;
import org.jsola.hr.dto.*;
import org.jsola.hr.dto.excel.CompanyImportDTO;
import org.jsola.hr.entity.*;
import org.jsola.hr.exception.HrException;
import org.jsola.hr.provider.*;
import org.jsola.hr.query.CompanyQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.service.excel.CompanyImportListener;
import org.jsola.hr.vo.*;
import org.jsola.module.ModuleContext;
import org.jsola.recruit2.dto.CompanyUnitsAddDTO;
import org.jsola.salary.vo.SalaryTemplateVO;
import org.jsola.user.core.TokenUser;
import org.jsola.user.core.UserContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.io.File;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static org.jsola.file.constant.FileConstants.FILE_TIME_OUT;
import static org.jsola.hr.constant.HrPermissionConstants.HR_SUBJECT_TYPE;

/**
 * 用工单位
 *
 * @author zhr
 */
@Slf4j
@Service("hrCompanyServiceImpl")
public class CompanyServiceImpl implements ICompanyService {

    @Autowired
    private ICompanyDAO companyDAO;
    @Autowired
    private ICompanyModuleService companyModuleService;
    @Autowired
    private IEmpInfoService empInfoService;
    @Autowired
    private IContractProviderService contractProviderService;
    @Autowired
    private ISalaryTemplateProviderService salaryTemplateProviderService;
    @Autowired
    private ISocProgService socProgService;
    @Autowired
    private ICostBillService costBillService;
    @Autowired
    @Lazy
    private IChildCompanyService childCompanyService;
    @Autowired
    private INoticeProviderService noticeProviderService;
    @Autowired
    @Lazy
    private IGroupCompanyService groupCompanyService;
    @Autowired
    @Lazy
    private ISalaryCalculateRuleGroupService salaryCalculateRuleGroupService;
    @Autowired
    @Lazy
    private IApproProviderService approProviderService;
    @Autowired
    @Lazy
    private ICustomTemplateService customTemplateService;
    @Autowired
    @Lazy
    private ICompanySueService companySueService;
    @Autowired
    private IRecruitProviderService recruitProviderService;

    @Autowired
    private ICompanyAdditionalFieldsService companyAdditionalFieldsService;

    @Autowired
    private ICompanySaleRebatesRulesService companySaleRebatesRulesService;

    @Autowired
    private ICompanySaleUserService companySaleUserService;

    @Autowired
    private ICompanySaleServerService companySaleServerService;

    @Autowired
    private IAdminProviderService adminProviderService;


    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Integer synchronizationCompanyToRecruit(String[] companyIds, TokenUser tokenUser) {
        for (String companyId : companyIds) {
            CompanyVO companyVO = selectById(companyId, tokenUser.getSiteId());
            if (companyVO == null) {
                continue;
            }
            CompanyUnitsAddDTO companyUnitsAddDTO = new CompanyUnitsAddDTO();
            if (!StringUtils.isEmpty(companyVO.getLogo())) {
                companyUnitsAddDTO.setLogo(companyVO.getLogo());
            }
            if (!StringUtils.isEmpty(companyVO.getName())) {
                companyUnitsAddDTO.setName(companyVO.getName());
            }
            if (!StringUtils.isEmpty(companyVO.getLegalPerson())) {
                companyUnitsAddDTO.setLegalPerson(companyVO.getLegalPerson());
            }
            if (!StringUtils.isEmpty(companyVO.getTelephone())) {
                companyUnitsAddDTO.setCompanyTelephone(companyVO.getTelephone());
            }
            if (!StringUtils.isEmpty(companyVO.getAddress())) {
                companyUnitsAddDTO.setAddress(companyVO.getAddress());
            }
            companyUnitsAddDTO.setSourceType(2);
            recruitProviderService.saveCompany(companyUnitsAddDTO, tokenUser);
        }
        return null;
    }

    @Autowired
    private AsyncCompanyFature asyncCompanyFature;

    @Autowired
    private DataSourceTransactionManager transactionManager;

    @Override
    public CompanyVO save(CompanyAddDTO companyAddDTO, TokenUser tokenUser) {
        companyAddDTO.setName(companyAddDTO.getName().trim());
        // 创建一个事务
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        // 显式设置事务名称是只能通过编程完成的操作
        def.setName(HrConstants.TX);
        // 设置事务策略
        // 支持当前交易；如果不存在，请创建一个新的。类似于同名的EJB事务属性。这通常是事务定义的默认设置, 并且通常定义事务同步作用域。
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        // 开始事务
        TransactionStatus status = transactionManager.getTransaction(def);
        try {
            //添加前判断用工单位名是否重复
            List<CompanyDO> companyDOList = selectCompanyByName(companyAddDTO.getName(), tokenUser);
            if (!CollectionUtils.isEmpty(companyDOList)) {
                throw new HrException("添加失败,该企业下已有名为:\"" + companyAddDTO.getName() + "\"的用工单位");
            }
            CompanyVO companyVO = saveCompany(companyAddDTO, tokenUser);
            // 提交事务
            transactionManager.commit(status);
            return companyVO;
        } catch (Exception ex) {
            // 事务回滚
            transactionManager.rollback(status);
            throw ex;
        }
    }

    /**
     * 新建用工单位
     *
     * @param companyAddDTO 用工单位信息
     * @param tokenUser     登录用户
     * @return 用工单位
     */
    private CompanyVO saveCompany(CompanyAddDTO companyAddDTO, TokenUser tokenUser) {
        // 转DO
        CompanyDO companyDO = companyAddDTO.to(CompanyDO.class);
        // 保存
        companyDO = save(companyDO, tokenUser.getSiteId(), tokenUser.getUserId());
        // 保存用工单位和用工单位分组的关系
        List<String> groupIds = companyAddDTO.getGroupIds();
        if (!CollectionUtils.isEmpty(groupIds)) {
            // 去重
            groupIds = groupIds.parallelStream().distinct().collect(Collectors.toList());
            for (String groupId : groupIds) {
                GroupCompanyAddDTO groupCompanyAddDTO = new GroupCompanyAddDTO();
                groupCompanyAddDTO.setGroupId(groupId);
                groupCompanyAddDTO.setCompanyId(companyDO.getId());
                groupCompanyAddDTO.setIsAll(Boolean.FALSE);
                groupCompanyService.save(groupCompanyAddDTO, tokenUser);
            }
        }
        try {
            // 初始化通知规则
            initNoticeRuleSetting(companyDO.getId(), tokenUser);
        } catch (Exception e) {
            log.error("初始化用工单位通知规则设置失败,{}", e.getMessage());
        }

        // 组织架构中增加二级,公司
        ModuleContext moduleContext = new ModuleContext();
        moduleContext.setSiteId(tokenUser.getSiteId());
        moduleContext.setCurrUserId(tokenUser.getUserId());
        moduleContext.add("companyDO", companyDO);
        // 公司初始化调用
        moduleContext = companyModuleService.initCompany(moduleContext);
        // 修改公司中部门id
        String depId = moduleContext.get("depId");
        CompanyDO companyUp = new CompanyDO();
        companyUp.setId(companyDO.getId());
        companyUp.setDepId(depId);
        updateByIdSelective(companyUp, tokenUser.getSiteId(), tokenUser.getUserId());

        HrLogKit.logForSave("新增公司,公司名:" + companyDO.getName(), "saveCompany",
                companyDO.getId(), companyDO.getId(), tokenUser);
        List<String> errorList = addAdvancedConfiguration(companyDO.getId(), companyAddDTO, tokenUser);
        CompanyVO companyVO = companyDO.to(CompanyVO.class);
        companyVO.setErrorList(errorList);
        return companyVO;
    }

    @Override
    public CompanyImportExcelVO importFile(File file, TokenUser tokenUser, Boolean force) {
        CompanyImportListener companyImportListener = new CompanyImportListener();
        companyImportListener.setTokenUser(tokenUser);
        companyImportListener.setParseOnly(false);
        companyImportListener.setForce(force);
        // 读取excel入库
        EasyExcel.read(file, CompanyImportDTO.class, companyImportListener).sheet().doRead();
        return companyImportListener.getCompanyImportExcelVO();
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public CompanyVO saveNoException(CompanyAddDTO companyAddDTO, TokenUser tokenUser) {
        //添加前判断用工单位名是否重复
        List<CompanyDO> companyDOList = selectCompanyByName(companyAddDTO.getName(), tokenUser);
        CompanyVO companyVO = new CompanyVO();
        if (!CollectionUtils.isEmpty(companyDOList)) {
            companyVO.setName("用工单位名不能为空或重复");
            return companyVO;
        }
        // 校验数据
        if (!checkCompanyAddDTOInfo(companyAddDTO, companyVO)) {
            return companyVO;
        }

        String groupName = companyAddDTO.getGroupName();
        if (org.apache.commons.lang3.StringUtils.isNotBlank(groupName)) {
            log.info("groupName: " + groupName);
            List<String> groupIds = new ArrayList<>();
            List<String> groupNameList = new ArrayList<>();
            if (groupName.contains(",")) {
                String[] groupNameArr = groupName.split(",");
                groupNameList = Arrays.asList(groupNameArr);
            } else if (groupName.contains("，")) {
                String[] groupNameArr = groupName.split("，");
                groupNameList = Arrays.asList(groupNameArr);
            } else {
                groupNameList.add(groupName);
            }

            //根据分组名查询分组id
            for (String s : groupNameList) {
                ChildCompanyDO childCompanyDO = childCompanyService.selectByName(s, tokenUser);
                if (childCompanyDO == null) {
                    companyVO.setName("用工单位分组不存在: " + s);
                    return companyVO;
                } else {
                    //保存公司和分组的关联关系
                    groupIds.add(childCompanyDO.getId());
                }
            }
            companyAddDTO.setGroupIds(groupIds);
        }

        //保存公司信息
        CompanyVO result = saveCompany(companyAddDTO, tokenUser);
        return result;
    }

    /**
     * 检查用工单位的信息是否符合规范
     *
     * @param companyAddDTO 用工单位信息
     * @return 是否符合
     */
    private boolean checkCompanyAddDTOInfo(CompanyAddDTO companyAddDTO, CompanyVO companyVO) {
        // 检查公司名称
        if (StrKit.isEmpty(companyAddDTO.getName())
                || companyAddDTO.getName().length() > 100) {
            companyVO.setName("用工单位不能为空或长度不能超过100");
            return false;
        }
        // 检查联系人姓名
        if (StrKit.isNotEmpty(companyAddDTO.getLegalPerson())
                && companyAddDTO.getLegalPerson().length() > 20) {
            companyVO.setName("联系人姓名长度不能超过20");
            return false;
        }
        // 验证手机号格式
        if (StrKit.isNotEmpty(companyAddDTO.getTelephone())) {
            String phoneRegex = "^[1][3,4,5,6,7,8,9][0-9]{9}$";
            Pattern p = Pattern.compile(phoneRegex);
            Matcher m = p.matcher(companyAddDTO.getTelephone());
            if (!m.matches()) {
                companyVO.setName("手机号格式不对");
                return false;
            }
        }
        // 验证邮箱格式
        if (StrKit.isNotEmpty(companyAddDTO.getEmail())) {
            if (companyAddDTO.getEmail().length() > 50) {
                companyVO.setName("邮箱长度不能超过50");
                return false;
            }
            String emailRegex = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
            Pattern p = Pattern.compile(emailRegex);
            Matcher m = p.matcher(companyAddDTO.getEmail());
            if (!m.matches()) {
                companyVO.setName("邮箱格式不对");
                return false;
            }
        }
        // 检查备注
        if (StrKit.isNotEmpty(companyAddDTO.getProfile()) && companyAddDTO.getProfile().length() > 500) {
            companyVO.setName("备注长度不能超过500");
            return false;
        }
        return true;
    }

    /**
     * 初始化用工规则设置
     */
    void initNoticeRuleSetting(String companyId, TokenUser tokenUser) {
        //
        // List<String> userIdList = userProviderService.selectUserIdHasRoleInCompany(companyId, tokenUser.getSiteId());
        List<String> userIdList = new ArrayList<>();
        noticeProviderService.initNoticeRuleSettingByCompanyId(userIdList, HR_SUBJECT_TYPE, companyId, tokenUser);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(CompanyUpdateDTO companyUpdateDTO, TokenUser tokenUser) {
        companyUpdateDTO.setName(companyUpdateDTO.getName().trim());
        //修改前判断用工单位名是否重复
        //查询到所有名称为要修改的名称的公司
        List<CompanyDO> companyDOList = selectCompanyByName(companyUpdateDTO.getName(), tokenUser);
        //过滤掉自己
        List<CompanyDO> companyDOListFilter = companyDOList
                .stream()
                .filter(companyDO -> !companyDO.getId().equals(companyUpdateDTO.getId()))
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(companyDOListFilter)) {
            throw new HrException("修改失败,该企业下已有名为:\"" + companyUpdateDTO.getName() + "\"的用工单位");
        }
        // 旧的
        CompanyDO companyOld = selectDOById(companyUpdateDTO.getId(), tokenUser.getSiteId());
        if (Objects.isNull(companyOld)) {
            return 0;
        }
        //转DO
        CompanyDO companyDO = companyUpdateDTO.to(CompanyDO.class);
        //根据主键更新，只更新非null值
        int upCount = updateByIdSelective(companyDO, tokenUser.getSiteId(), tokenUser.getUserId());
        // 修改姓名时同步修改组织架构中层级
        if (!StringUtils.isEmpty(companyUpdateDTO.getName()) && !companyOld.getName().equals(companyUpdateDTO.getName())) {
            // 组织架构中增加二级,公司
            ModuleContext moduleContext = new ModuleContext();
            moduleContext.setSiteId(tokenUser.getSiteId());
            moduleContext.setCurrUserId(tokenUser.getUserId());
            moduleContext.add("companyDO", companyDO);
            companyModuleService.updateCompany(moduleContext);
        }
        List<CostBillDO> costBillList = costBillService.selectByCompanyId(companyUpdateDTO.getId(), tokenUser);
        for (CostBillDO costBillDO : costBillList) {
            if (!companyUpdateDTO.getName().equals(costBillDO.getCompanyName())) {
                costBillDO.setCompanyName(companyUpdateDTO.getName());
                costBillService.updateByIdSelective(costBillDO, tokenUser.getSiteId(), tokenUser.getUserId());
            }
        }
        // 返费规则
        CompanySaleRebatesRulesDO companySaleRebatesRules = companySaleRebatesRulesService
                .selectRulesByCompanyId(companyDO.getId(), tokenUser.getSiteId());
        if (StringUtils.isEmpty(companyUpdateDTO.getSaleRulesId())) {
            if (!ObjectUtils.isEmpty(companySaleRebatesRules)) {
                companySaleRebatesRules.setValid(false);
                companySaleRebatesRules.setRemark(new Date() + "-编辑用工单位删除提成规则");
                companySaleRebatesRulesService.updateByIdSelective(companySaleRebatesRules);
            }
        } else {
            if (!ObjectUtils.isEmpty(companySaleRebatesRules) &&
                    !companySaleRebatesRules.getRebatesRulesId().equals(companyUpdateDTO.getSaleRulesId())) {
                CompanySaleRebatesRulesAddDTO insert = new CompanySaleRebatesRulesAddDTO();
                companySaleRebatesRules.setValid(false);
                companySaleRebatesRulesService.updateByIdSelective(companySaleRebatesRules);
                insert.setRemark(new Date() +
                        "-编辑用工单位修改提成规则,原规则Id" + companySaleRebatesRules.getId());
                insert.setCompanyId(companyDO.getId());
                insert.setRebatesRulesId(companyUpdateDTO.getSaleRulesId());
                companySaleRebatesRulesService.save(insert, tokenUser);
            } else if (ObjectUtils.isEmpty(companySaleRebatesRules)) {
                CompanySaleRebatesRulesAddDTO insert = new CompanySaleRebatesRulesAddDTO();
                insert.setCompanyId(companyDO.getId());
                insert.setRebatesRulesId(companyUpdateDTO.getSaleRulesId());
                companySaleRebatesRulesService.save(insert, tokenUser);
            }
        }
        // 所属销售 为了好追溯删了再加
        companySaleUserService.deleteFromCompany(companyDO.getId(), tokenUser);
        List<CompanySaleUserAddDTO> saleUserList = companyUpdateDTO.getSaleUserList();
        if (!CollectionUtils.isEmpty(saleUserList)) {
            List<BigDecimal> proportionList = saleUserList.stream()
                    .map(CompanySaleUserAddDTO::getDividedProportion).collect(Collectors.toList());
            BigDecimal bigDecimal = new BigDecimal("0");
            for (BigDecimal proportion : proportionList) {
                bigDecimal = bigDecimal.add(proportion);
            }
            if (bigDecimal.compareTo(new BigDecimal("100")) != 0) {
                throw new ParamException("销售分成比例之和必须为100%");
            }
            companySaleUserService.bachSave(saleUserList, tokenUser);
        }
        // 销售-合同信息 为了好追溯删了再加
        companySaleServerService.deleteFromCompany(companyDO.getId(), tokenUser);
        String companyId = companyDO.getId();
        if (!CollectionUtils.isEmpty(companyUpdateDTO.getCompanySaleServerList())) {
            // 校验时间是否有重叠
            companySaleServerService.checkServerTime(companyUpdateDTO.getCompanySaleServerList());
            List<CompanySaleServerDO> serverList = companySaleServerService
                    .bachSave(companyUpdateDTO.getCompanySaleServerList(), tokenUser);
            companySaleServerService.addServetTask(serverList, companyId, tokenUser);
        }
        HrLogKit.logForUpdate("由管理员" + tokenUser.getUserName() + "修改用工单位",
                "updateCompany", companyId, companyId, tokenUser);
        // 删除原有用工单位所在分组
        List<GroupCompanyDO> groupCompanyDOList = groupCompanyService.selectByCompanyIds(
                Collections.singletonList(companyId), tokenUser.getSiteId());
        groupCompanyService.deleteByIds(tokenUser, groupCompanyDOList.parallelStream().map(BaseDO::getId).toArray(String[]::new));
        // 修改用工单位分组
        List<String> groupIds = companyUpdateDTO.getGroupIds();
        if (!CollectionUtils.isEmpty(groupIds)) {
            // 去重
            groupIds = groupIds.parallelStream().distinct().collect(Collectors.toList());
            for (String groupId : groupIds) {
                GroupCompanyAddDTO groupCompanyAddDTO = new GroupCompanyAddDTO();
                groupCompanyAddDTO.setGroupId(groupId);
                groupCompanyAddDTO.setCompanyId(companyId);
                groupCompanyAddDTO.setIsAll(Boolean.FALSE);
                groupCompanyService.save(groupCompanyAddDTO, tokenUser);
            }
        }
        return upCount;
    }

    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    @Override
    public List<String> addAdvancedConfiguration(String companyId, CompanyAddDTO companyAddDTO, TokenUser tokenUser) {
        List<String> errorList = new ArrayList<>();
        final CountDownLatch countDownLatch = new CountDownLatch(7);
        AddAdvancedConfigurationDTO addAdvancedConfigurationDTO = new AddAdvancedConfigurationDTO();
        addAdvancedConfigurationDTO.setCompanyId(companyId);
        addAdvancedConfigurationDTO.setCompanyName(companyAddDTO.getName());
        addAdvancedConfigurationDTO.setCountDownLatch(countDownLatch);

        // 合同模板
        List<IssuedCategoryAddDTO.Category> categoryList = companyAddDTO.getCategoryList();
        if (!CollectionUtils.isEmpty(categoryList)) {
            // 同步下发印章
            if (companyAddDTO.getIsSeal() != null && companyAddDTO.getIsSeal()) {
                // 查询含有哪些印章
                List<Long> categoryIdList = new ArrayList<>();
                for (IssuedCategoryAddDTO.Category category : categoryList) {
                    List<Long> categoryIds = category.getCategoryIds();
                    if (!CollectionUtils.isEmpty(categoryIds)) {
                        categoryIdList.addAll(categoryIds);
                    }
                }
                List<CategoryDO> categoryDOList = contractProviderService.selectCategoryByIds(categoryIdList);
                // 企业印章Ids
                List<Long> enterpriseSealIds = categoryDOList.parallelStream().map(CategoryDO::getEnterpriseSealId)
                        .collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(enterpriseSealIds)) {
                    List<Long> sealsIds = companyAddDTO.getSealsIds();
                    if (CollectionUtils.isEmpty(sealsIds)) {
                        sealsIds = new ArrayList<>();
                    }
                    // 去重
                    sealsIds = sealsIds.parallelStream().distinct().collect(Collectors.toList());
                    sealsIds.removeAll(enterpriseSealIds);
                    companyAddDTO.setSealsIds(sealsIds);
                }
            }
            companySueService.sueCategory(addAdvancedConfigurationDTO, categoryList, companyAddDTO.getIsSeal(), tokenUser);
        } else {
            addAdvancedConfigurationDTO.setCategory(0L);
            countDownLatch.countDown();
        }

        // 工价/劳务费规则
        List<String> salaryCalculateRuleGroupIdList = companyAddDTO.getSalaryCalculateRuleGroupIdList();
        if (!CollectionUtils.isEmpty(salaryCalculateRuleGroupIdList)) {
            companySueService.sueSalaryCalculateRuleGroup(addAdvancedConfigurationDTO, salaryCalculateRuleGroupIdList, tokenUser);
        } else {
            addAdvancedConfigurationDTO.setSalaryCalculate(0L);
            countDownLatch.countDown();
        }

        // 月工资模板
        List<Long> salaryTemplateIds = companyAddDTO.getSalaryTemplateIds();
        if (!CollectionUtils.isEmpty(salaryTemplateIds)) {
            companySueService.sueSalaryTemplate(addAdvancedConfigurationDTO, salaryTemplateIds, tokenUser);
        } else {
            addAdvancedConfigurationDTO.setSalaryTemplate(0L);
            countDownLatch.countDown();
        }

        // 审批
        List<IssuedApproFlowAddDTO.ApproFlowInfor> approFlowInforList = companyAddDTO.getApproFlowInforList();
        if (!CollectionUtils.isEmpty(approFlowInforList)) {
            companySueService.suedApproFlow(addAdvancedConfigurationDTO, approFlowInforList, tokenUser);
        } else {
            addAdvancedConfigurationDTO.setApproFlow(0L);
            countDownLatch.countDown();
        }

        // 新建用工单位  下发租户级自定义字段到用工单位
        issuedAdditionalFields(companyId, tokenUser);

        // 入职模板
        List<String> templateIds = companyAddDTO.getTemplateIds();
        // 查询租户下默认模板 自动下发
        List<CustomTemplateDO> customTemplateDOList = customTemplateService
                .selectDefaultBySite(tokenUser.getSiteId());
        if (!CollectionUtils.isEmpty(customTemplateDOList)) {
            if (CollectionUtils.isEmpty(templateIds)) {
                templateIds = new ArrayList<>();
            }
            // 默认模板自动下发
            templateIds.addAll(customTemplateDOList.parallelStream().map(BaseDO::getId).collect(Collectors.toList()));
            // 去重
            templateIds = templateIds.parallelStream().distinct().collect(Collectors.toList());
        }
        if (!CollectionUtils.isEmpty(templateIds)) {
            companySueService.sueTemplate(addAdvancedConfigurationDTO, templateIds, tokenUser);
        } else {
            addAdvancedConfigurationDTO.setTemplate(0L);
            countDownLatch.countDown();
        }

        // 参保方案
        List<String> socProgsIds = companyAddDTO.getSocProgsIds();
        if (!CollectionUtils.isEmpty(socProgsIds)) {
            companySueService.suedSocProg(addAdvancedConfigurationDTO, socProgsIds, tokenUser);
        } else {
            addAdvancedConfigurationDTO.setSocProg(0L);
            countDownLatch.countDown();
        }

        // 印章
        List<Long> sealsIds = companyAddDTO.getSealsIds();
        if (!CollectionUtils.isEmpty(sealsIds)) {
            companySueService.suedSeal(addAdvancedConfigurationDTO, sealsIds, tokenUser);
        } else {
            addAdvancedConfigurationDTO.setSeal(0L);
            countDownLatch.countDown();
        }
        // 返费规则
        if (!StringUtils.isEmpty(companyAddDTO.getSaleRulesId())) {
            CompanySaleRebatesRulesAddDTO companySaleRebatesRules = new CompanySaleRebatesRulesAddDTO();
            companySaleRebatesRules.setCompanyId(companyId);
            companySaleRebatesRules.setRebatesRulesId(companyAddDTO.getSaleRulesId());
            companySaleRebatesRulesService.save(companySaleRebatesRules, tokenUser);
        }
        // 所属销售
        List<CompanySaleUserAddDTO> saleUserList = companyAddDTO.getSaleUserList();
        if (!CollectionUtils.isEmpty(saleUserList)) {
            for (CompanySaleUserAddDTO companySaleUser : saleUserList) {
                companySaleUser.setCompanyId(companyId);
            }
            companySaleUserService.bachSave(saleUserList, tokenUser);
        }
        // 销售-合同信息
        List<CompanySaleServerAddDTO> companySaleServerList = companyAddDTO.getCompanySaleServerList();
        if (!CollectionUtils.isEmpty(companySaleServerList)) {
            // 校验时间是否有重叠
            companySaleServerService.checkServerTime(companySaleServerList);
            for (CompanySaleServerAddDTO companySaleServer : companySaleServerList) {
                companySaleServer.setCompanyId(companyId);
            }
            List<CompanySaleServerDO> serverList = companySaleServerService.bachSave(companySaleServerList, tokenUser);
            companySaleServerService.addServetTask(serverList, companyId, tokenUser);
        }
        try {
            if (!countDownLatch.await(FILE_TIME_OUT, TimeUnit.MILLISECONDS)) {
                log.error("创建用工单位，下发模板超时，下发工价/劳务费规则用时：{}，下发合同模板用时：{}" +
                                "，下发月工资模板用时：{}，下发审批用时：{}，下发入职模板用时：{}，下发参保方案用时：{}，下发印章用时：{}",
                        addAdvancedConfigurationDTO.getSalaryCalculate(), addAdvancedConfigurationDTO.getCategory()
                        , addAdvancedConfigurationDTO.getSalaryTemplate(), addAdvancedConfigurationDTO.getApproFlow()
                        , addAdvancedConfigurationDTO.getTemplate(), addAdvancedConfigurationDTO.getSocProg()
                        , addAdvancedConfigurationDTO.getSeal());
                throw new ParamException("下发模板过多，请创建用工单位后分批下发");
            }
            // 错误列表
            log.info("下发总线程：{}执行完成了", Thread.currentThread().getName());
            if (addAdvancedConfigurationDTO.getSalaryCalculate() == null) {
                errorList.add("下发工价/劳务费规则失败");
            }
            if (addAdvancedConfigurationDTO.getCategory() == null) {
                errorList.add("下发合同模版列表失败");
            }
            if (addAdvancedConfigurationDTO.getSalaryTemplate() == null) {
                errorList.add("下发月工资模板失败");
            }
            if (addAdvancedConfigurationDTO.getApproFlow() == null) {
                errorList.add("下发审批失败");
            }
            if (addAdvancedConfigurationDTO.getTemplate() == null) {
                errorList.add("下发入职模板失败");
            }
            if (addAdvancedConfigurationDTO.getSocProg() == null) {
                errorList.add("下发参保方案失败");
            }
            if (addAdvancedConfigurationDTO.getSeal() == null) {
                errorList.add("下发印章失败");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return errorList;
    }


    /**
     * 下发租户的可选自定义信息到用工单位
     *
     * @param companyId 用工单位Id
     * @param tokenUser 登录用户
     */
    private void issuedAdditionalFields(String companyId, TokenUser tokenUser) {
        // 租户下自定义字段
        List<CompanyAdditionalFieldsListVO> siteAdditionalFieldsListVOList = companyAdditionalFieldsService
                .selectByCompanyId2("site", null, tokenUser.getSiteId());

        // 用工单位下自定义字段
        List<CompanyAdditionalFieldsListVO> companyAdditionalFieldsListVOList = companyAdditionalFieldsService
                .selectByCompanyId2(companyId, null, tokenUser.getSiteId());
        for (CompanyAdditionalFieldsListVO siteAdditionalFieldsListVO : siteAdditionalFieldsListVOList) {
            boolean needSave = Boolean.TRUE;
            for (CompanyAdditionalFieldsListVO companyAdditionalFieldsListVO : companyAdditionalFieldsListVOList) {
                // 字段名称和模块都一致 视为同一字段 将租户设置放入用工单位模板中
                if (companyAdditionalFieldsListVO.getModuleCode().equals(siteAdditionalFieldsListVO.getModuleCode())
                        && companyAdditionalFieldsListVO.getFieldName().equals(siteAdditionalFieldsListVO.getFieldName())) {
                    CompanyAdditionalFieldsDO companyAdditionalDO = siteAdditionalFieldsListVO.to(CompanyAdditionalFieldsDO.class);
                    companyAdditionalDO.setId(companyAdditionalFieldsListVO.getId());
                    companyAdditionalDO.setCompanyId(companyId);
                    companyAdditionalDO.setTemplateId(null);
                    companyAdditionalFieldsService.updateByIdSelective(companyAdditionalDO
                            , tokenUser.getSiteId(), tokenUser.getUserId());
                    needSave = Boolean.FALSE;
                    break;
                }
            }
            // 租户模板中字段在用工单位模板中不存在 新增
            if (needSave) {
                CompanyAdditionalFieldsDO companyAdditionalDO = siteAdditionalFieldsListVO.to(CompanyAdditionalFieldsDO.class);
                companyAdditionalDO.setCompanyId(companyId);
                companyAdditionalDO.setTemplateId(null);
                companyAdditionalDO.setId(null);
                companyAdditionalFieldsService.save(companyAdditionalDO, tokenUser.getSiteId(), tokenUser.getUserId());
            }
        }
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... companyIds) {
        CompanyDO companyDO = selectDOById(companyIds[0], tokenUser.getSiteId());
        for (String companyId : companyIds) {
            // 校验能否删除
            checkCanDelete(companyId, tokenUser.getSiteId());
        }
        // 组织架构中删除公司
        ModuleContext moduleContext = new ModuleContext();
        moduleContext.setSiteId(tokenUser.getSiteId());
        moduleContext.setCurrUserId(tokenUser.getUserId());
        moduleContext.add("companyIds", companyIds);
        companyModuleService.destroyCompany(moduleContext);
        int delCount = logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) companyIds);
        if (companyIds.length > 1) {
            HrLogKit.logForDelete("由管理员" + tokenUser.getUserName() +
                    "批量删除 " + companyDO.getName() + "等" + companyIds.length +
                    "家用工单位", "Company", tokenUser.getUserId(), tokenUser);
        } else {
            HrLogKit.logForDelete("由管理员" + tokenUser.getUserName() + "删除用工单位:" +
                    companyDO.getName(), "Company", tokenUser.getUserId(), companyDO.getId(), tokenUser);
        }
        // 查询含有该用工单位的分组 若用工单位都被删除 则删除分组
        List<GroupCompanyDO> groupCompanyDOList = groupCompanyService
                .selectByCompanyIds(Arrays.asList(companyIds.clone()), tokenUser.getSiteId());
        if (!CollectionUtils.isEmpty(groupCompanyDOList)) {
            // 含有删除用工单位的分组
            List<String> groupIds = groupCompanyDOList.parallelStream().map(GroupCompanyDO::getGroupId).distinct().collect(Collectors.toList());
            // 删除 分组与待删除用工单位的关系
            groupCompanyService.deleteByIds(tokenUser, groupCompanyDOList.parallelStream().map(BaseDO::getId).toArray(String[]::new));
            // 查询分组下的用工单位
            List<GroupCompanyDO> nowList = groupCompanyService.selectByGroupIds(groupIds, tokenUser.getSiteId());
            if (CollectionUtils.isEmpty(nowList)) {
                childCompanyService.deleteByIds(tokenUser, groupIds.toArray(new String[0]));
            } else {
                Map<String, List<GroupCompanyDO>> groupIdListMap = nowList.parallelStream()
                        .collect(Collectors.groupingBy(GroupCompanyDO::getGroupId));
                for (String groupId : groupIdListMap.keySet()) {
                    // 分组下无其他用工单位 删除分组
                    if (CollectionUtils.isEmpty(groupIdListMap.get(groupId))) {
                        childCompanyService.deleteByIds(tokenUser, groupId);
                    }
                }
            }
        }
        return delCount;
    }

    /**
     * 校验能否删除
     *
     * @param companyId 公司id
     * @param siteId    站点
     */
    private void checkCanDelete(String companyId, String siteId) {
        List<EmpInfoDO> empInfoList = empInfoService.listOnJobByCompanyId(companyId, siteId);
        if (!CollectionUtils.isEmpty(empInfoList)) {
            throw new ParamException("公司内尚有在职的员工,请先处理");
        }
    }


    @Override
    public CompanyVO selectById(String companyId, String siteId) {
        CompanyDO companyDO = selectDOById(companyId, siteId);
        if (companyDO == null) {
            return null;
        }
        CompanyVO companyVO = companyDO.to(CompanyVO.class);
        if (companyVO != null) {
            TokenUser tokenUser = UserContext.getUser();
            // 参保方案id
            List<SocProgDO> socProgList = new ArrayList<>();
            // 参保方案id
            List<CategoryDO> categoryList = new ArrayList<>();
            // 工资表模板id
            List<SalaryTemplateVO> salaryTemplateList = new ArrayList<>();
            // 合同印章id
            List<SealDO> sealList = new ArrayList<>();

            List<SocProgDO> socProgDOList = socProgService.selectSocProgByCompanyId(companyId, tokenUser);
            if (!CollectionUtils.isEmpty(socProgDOList)) {
                socProgList = socProgDOList.stream().filter(s -> Boolean.TRUE.equals(s.getIssue()))
                        .collect(Collectors.toList());
            }
            companyVO.setSocProgList(socProgList);

            // 写入合同模板
            List<CategoryDO> categoryDOList = contractProviderService.listBySubjectId(companyId, tokenUser.getSiteId());
            if (!CollectionUtils.isEmpty(categoryDOList)) {
                categoryList = categoryDOList.stream().filter(s -> Boolean.TRUE.equals(s.getIssue()))
                        .collect(Collectors.toList());
            }
            companyVO.setCategoryList(categoryList);

            // 写入工资表模板
            List<SalaryTemplateVO> salaryTemplateVOList = salaryTemplateProviderService.selectByCompanyId(companyId, tokenUser);
            if (!CollectionUtils.isEmpty(salaryTemplateVOList)) {
                salaryTemplateList = salaryTemplateVOList.stream().filter(s -> Boolean.TRUE.equals(s.getIssue()))
                        .collect(Collectors.toList());
            }
            companyVO.setSalaryTemplateList(salaryTemplateList);

            // 合同印章
            List<SealDO> sealDOList = contractProviderService.selectBySubjectId(companyId, tokenUser.getSiteId());
            if (!CollectionUtils.isEmpty(sealDOList)) {
                sealList = sealDOList.stream().filter(s -> Boolean.TRUE.equals(s.getIssue()))
                        .collect(Collectors.toList());
            }
            companyVO.setSealList(sealList);
        }
        return companyVO;
    }

    @Override
    public CompanyVO selectById(String companyId, TokenUser tokenUser) {
        CompanyDO companyDO = selectDOById(companyId, tokenUser.getSiteId());
        if (companyDO == null) {
            return null;
        }
        CompanyVO companyVO = companyDO.to(CompanyVO.class);
        if (companyVO != null) {
            // 参保方案id
            List<SocProgDO> socProgList = new ArrayList<>();
            // 参保方案id
            List<CategoryDO> categoryList = new ArrayList<>();
            // 工资表模板id
            List<SalaryTemplateVO> salaryTemplateList = new ArrayList<>();
            // 合同印章id
            List<SealDO> sealList = new ArrayList<>();

            // 工价/劳务费规则
            List<SalaryCalculateRuleGroupDO> salaryCalculateRuleGroupDOList = salaryCalculateRuleGroupService
                    .selectHadSourceByCompanyId(companyId, tokenUser);
            companyVO.setSalaryCalculateRuleGroupDOList(salaryCalculateRuleGroupDOList);

            // 合同模板
            List<CategoryDO> categoryDOList = contractProviderService.listBySubjectId(companyId, tokenUser.getSiteId());
            if (!CollectionUtils.isEmpty(categoryDOList)) {
                categoryList = categoryDOList.stream().filter(s -> Boolean.TRUE.equals(s.getIssue()))
                        .collect(Collectors.toList());
            }
            companyVO.setCategoryList(categoryList);

            // 工资表模板
            List<SalaryTemplateVO> salaryTemplateVOList = salaryTemplateProviderService.selectByCompanyId(companyId, tokenUser);
            if (!CollectionUtils.isEmpty(salaryTemplateVOList)) {
                salaryTemplateList = salaryTemplateVOList.stream().filter(s -> Boolean.TRUE.equals(s.getIssue()))
                        .collect(Collectors.toList());
            }
            companyVO.setSalaryTemplateList(salaryTemplateList);

            // 审批
            List<ApproFlowListVO> approFlowListVOList = approProviderService
                    .selectAllFlowsByCompany(companyId, tokenUser.getSiteId());
            if (!CollectionUtils.isEmpty(approFlowListVOList)) {
                approFlowListVOList = approFlowListVOList.stream().filter(s -> StringUtils.hasLength(s.getSourceId()))
                        .collect(Collectors.toList());
            }
            companyVO.setApproFlowListVOList(approFlowListVOList);

            // 入职模板
            List<CustomTemplateDO> customTemplateDOList = customTemplateService.selectByCompanyId(companyId, null, null, tokenUser);
            if (!CollectionUtils.isEmpty(customTemplateDOList)) {
                customTemplateDOList = customTemplateDOList.stream().filter(s -> StringUtils.hasLength(s.getSiteId()))
                        .collect(Collectors.toList());
            }
            companyVO.setCustomTemplateDOList(customTemplateDOList);

            // 参保方案id
            List<SocProgDO> socProgDOList = socProgService.selectSocProgByCompanyId(companyId, tokenUser);
            if (!CollectionUtils.isEmpty(socProgDOList)) {
                socProgList = socProgDOList.stream().filter(s -> Boolean.TRUE.equals(s.getIssue()))
                        .collect(Collectors.toList());
            }
            companyVO.setSocProgList(socProgList);

            // 合同印章
            List<SealDO> sealDOList = contractProviderService.selectBySubjectId(companyId, tokenUser.getSiteId());
            if (!CollectionUtils.isEmpty(sealDOList)) {
                sealList = sealDOList.stream().filter(s -> Boolean.TRUE.equals(s.getIssue()))
                        .collect(Collectors.toList());
            }
            companyVO.setSealList(sealList);
        }
        return companyVO;
    }

    @Override
    public CompanyVO selectCompanyInfoByIdASync(String companyId, TokenUser tokenUser) {
        try {
            CompanyDO companyDO = selectDOById(companyId, tokenUser.getSiteId());
            if (companyDO == null) {
                return null;
            }
            CompanyVO companyVO = companyDO.to(CompanyVO.class);
            if (companyVO == null) {
                return companyVO;
            }
            //参保方案
            Future<List<SocProgDO>> taskSocProg = asyncCompanyFature.taskSocProg(companyId, tokenUser);
            //合同模板
            Future<List<CategoryDO>> taskCategory = asyncCompanyFature.taskCategory(companyId, tokenUser);
            //工资表模板
            Future<List<SalaryTemplateVO>> taskSalaryTemplate = asyncCompanyFature.taskSalaryTemplate(companyId, tokenUser);
            //合同印章
            Future<List<SealDO>> taskSeal = asyncCompanyFature.taskSeal(companyId, tokenUser);
            // 工价/劳务费规则
            Future<List<SalaryCalculateRuleGroupDO>> taskSalaryCalculateRuleGroup = asyncCompanyFature.taskSalaryCalculateRuleGroup(companyId, tokenUser);
            // 审批
            Future<List<ApproFlowListVO>> taskApproFlowList = asyncCompanyFature.taskApproFlowList(companyId, tokenUser);
            // 入职模板
            Future<List<CustomTemplateDO>> taskcustomTemplate = asyncCompanyFature.taskcustomTemplate(companyId, tokenUser);
            // 返费规则
            Future<SaleRebatesRulesDO> saleRebatesRules = asyncCompanyFature.selectCompanyRules(companyId, tokenUser);
            // 所属销售
            Future<List<CompanySaleUserDO>> companySaleUser = asyncCompanyFature.selectCompanySaleUser(companyId, tokenUser);
            // 销售-合同信息
            Future<List<CompanySaleServerDO>> saleServer = asyncCompanyFature.selectCompanySaleServer(companyId, tokenUser);
            List<SocProgDO> socProgList = taskSocProg.get();
            if (CollectionUtils.isEmpty(socProgList)) {
                companyVO.setSocProgList(new ArrayList<>());
            } else {
                companyVO.setSocProgList(socProgList);
            }

            List<CategoryDO> categoryList = taskCategory.get();
            if (CollectionUtils.isEmpty(categoryList)) {
                companyVO.setCategoryList(new ArrayList<>());
            } else {
                companyVO.setCategoryList(categoryList);
            }

            // 工资表模板
            List<SalaryTemplateVO> salaryTemplateVOList = taskSalaryTemplate.get();
            if (CollectionUtils.isEmpty(salaryTemplateVOList)) {
                companyVO.setSalaryTemplateList(new ArrayList<>());
            } else {
                companyVO.setSalaryTemplateList(salaryTemplateVOList);
            }

            // 合同印章
            List<SealDO> sealDOList = taskSeal.get();
            if (CollectionUtils.isEmpty(sealDOList)) {
                companyVO.setSealList(new ArrayList<>());
            } else {
                companyVO.setSealList(sealDOList);
            }

            // 工价/劳务费规则
            List<SalaryCalculateRuleGroupDO> salaryCalculateRuleGroupDOList = taskSalaryCalculateRuleGroup.get();
            if (CollectionUtils.isEmpty(salaryCalculateRuleGroupDOList)) {
                companyVO.setSalaryCalculateRuleGroupDOList(new ArrayList<>());
            } else {
                companyVO.setSalaryCalculateRuleGroupDOList(salaryCalculateRuleGroupDOList);
            }

            // 审批
            List<ApproFlowListVO> approFlowListVOList = taskApproFlowList.get();
            if (CollectionUtils.isEmpty(approFlowListVOList)) {
                companyVO.setApproFlowListVOList(new ArrayList<>());
            } else {
                companyVO.setApproFlowListVOList(approFlowListVOList);
            }

            // 入职模板
            List<CustomTemplateDO> customTemplateDOList = taskcustomTemplate.get();
            if (CollectionUtils.isEmpty(customTemplateDOList)) {
                companyVO.setCustomTemplateDOList(new ArrayList<>());
            } else {
                companyVO.setCustomTemplateDOList(customTemplateDOList);
            }
            // 返费规则
            SaleRebatesRulesDO saleRules = saleRebatesRules.get();
            if (!ObjectUtils.isEmpty(saleRules)) {
                companyVO.setSaleRebatesRules(saleRules);
            }
            // 所属销售
            List<CompanySaleUserDO> companySaleUserList = companySaleUser.get();
            if (CollectionUtils.isEmpty(companySaleUserList)) {
                companyVO.setCompanySaleUser(new ArrayList<>());
            } else {
                companyVO.setCompanySaleUser(companySaleUserList);
            }
            // 销售-合同信息
            List<CompanySaleServerDO> companySaleServerList = saleServer.get();
            if (CollectionUtils.isEmpty(companySaleServerList)) {
                companyVO.setCompanySaleServer(new ArrayList<>());
            } else {
                companyVO.setCompanySaleServer(companySaleServerList);
            }
            // 查询用工单位所在分组
            List<GroupCompanyDO> groupCompanyDOList = groupCompanyService.selectByCompanyIds(
                    Collections.singletonList(companyId), tokenUser.getSiteId());
            companyVO.setGroupIds(groupCompanyDOList.parallelStream().map(GroupCompanyDO::getGroupId).collect(Collectors.toList()));

            // 判断是否在有效期内
            Boolean contractStatus = companySaleServerService.findContractStatus(companyId, tokenUser);
            companyVO.setContractStatus(contractStatus);

            return companyVO;
        } catch (Exception e) {
            log.error("selectCompanyInfoByIdASync 异常", e);
        }
        return null;
    }

    @Override
    public CompanyVO selectBaseCompanyById(String companyId, String siteId) {
        CompanyDO companyDO = selectDOById(companyId, siteId);
        if (companyDO == null) {
            return null;
        }
        return companyDO.to(CompanyVO.class);
    }

    @Override
    public List<CompanyDO> selectBaseCompanyByIdList(List<String> companyIdList, String siteId) {
        if (CollectionUtils.isEmpty(companyIdList)) {
            return new ArrayList<>();
        }
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andIn("id", companyIdList);
        return companyDAO.selectByExample(example);
    }

    @Override
    public List<CompanyDO> selectByIds(List<String> companyIdList, String siteId) {
        if (CollectionUtils.isEmpty(companyIdList)) {
            return new ArrayList<>();
        }
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (!CollectionUtils.isEmpty(companyIdList)) {
            example.and().andIn("id", companyIdList);
        }
        return companyDAO.selectByExample(example);
    }

    @Override
    public List<CompanyDO> selectByIdsNotSiteId(List<String> companyIdList) {

        if (CollectionUtils.isEmpty(companyIdList)) {
            return new ArrayList<>();
        }
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("valid", true);
        if (!CollectionUtils.isEmpty(companyIdList)) {
            example.and().andIn("id", companyIdList);
        }
        return companyDAO.selectByExample(example);
    }

    @Override
    public List<CompanyDO> selectAll() {
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("valid", true);
        return companyDAO.selectByExample(example);
    }

    @Override
    public List<CompanyDO> selectAll(String siteId) {
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        return companyDAO.selectByExample(example);
    }

    @Override
    public List<CompanyDO> selectByIdsContainDelete(List<String> companyIdList, String siteId) {
        if (CollectionUtils.isEmpty(companyIdList)) {
            return new ArrayList<>();
        }
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("siteId", siteId);
        if (!CollectionUtils.isEmpty(companyIdList)) {
            example.and().andIn("id", companyIdList);
        }
        return companyDAO.selectByExample(example);
    }

    @Override
    public List<CompanyListVO> select(CompanyQuery companyQuery, TokenUser tokenUser) {
        List<CompanyListVO> resultList = getVoListByDoList(selectDO(companyQuery, tokenUser));
        if (CollectionUtils.isEmpty(resultList)) {
            return new ArrayList<>();
        }
        // 判断查询出来的用工单位是否在合同有效期之内
        List<String> companyIdList = resultList.stream().map(CompanyListVO::getId).collect(Collectors.toList());
        List<CompanySaleServerDO> serverList = companySaleServerService
                .selectByCompanyIdList(companyIdList, tokenUser.getSiteId());
        Map<String, List<CompanySaleServerDO>> groupServerMap = serverList.stream()
                .collect(Collectors.groupingBy(CompanySaleServerDO::getCompanyId));
        for (CompanyListVO company : resultList) {
            List<CompanySaleServerDO> companySaleServerList = groupServerMap.get(company.getId());
            if (CollectionUtils.isEmpty(companySaleServerList)) {
                company.setContractStatus(true);
                continue;
            }
            boolean contractStatus = false;
            String yearMonthStr = DateUtils.getYearMonthStr(new Date());
            for (CompanySaleServerDO companySaleServer : companySaleServerList) {
                Date serverBeginTime = companySaleServer.getServerBeginTime();
                Date serverEndTime = companySaleServer.getServerEndTime();
                contractStatus = DateUtils.compareWithinRange(serverBeginTime, serverEndTime, yearMonthStr);
                if (contractStatus) {
                    break;
                }
            }
            company.setContractStatus(contractStatus);
        }
        return resultList;
    }

    @Override
    public List<CompanyListVO> selectCompanyList(TokenUser tokenUser) {
        CompanyQuery companyQuery = new CompanyQuery();
        return getVoListByDoList(selectDO(companyQuery, tokenUser));
    }

    /**
     * 根据doList获取voList
     *
     * @param doList do
     * @return vo
     */
    private List<CompanyListVO> getVoListByDoList(List<CompanyDO> doList) {
        if (CollectionUtils.isEmpty(doList)) {
            return doList == null ? null : new ArrayList<>();
        }
        return doList.stream().map(companyDO -> companyDO.to(CompanyListVO.class)).collect(Collectors.toList());
    }


    @Override
    public int selectCount(CompanyQuery companyQuery, String siteId) {
        Example example = buildExample(companyQuery, siteId);
        return companyDAO.selectCountByExample(example);
    }

    @Override
    public Page<CompanyListVO> selectPage(CompanyQuery companyQuery, TokenUser tokenUser) {
        Example example = buildExample(companyQuery, tokenUser.getSiteId());

        // 增加用户公司权限限制
        addUserCompanyRoleLimit(example, tokenUser);

        Page<CompanyDO> page = companyDAO.selectPageByExample(example,
                companyQuery.getPageNo(),
                companyQuery.getPageSize());
        if (CollectionUtils.isEmpty(page.getEntities())) {
            return new Page<>(companyQuery.getPageSize(), companyQuery.getPageNo());
        }
        List<CompanyListVO> companyList = page.getEntities().parallelStream().map(companyDO
                -> companyDO.to(CompanyListVO.class)).collect(Collectors.toList());
        return new Page<>(companyList, page.getPageNo(), page.getPageSize(), page.getEntityCount());
    }

    /**
     * 增加用户公司权限限制
     *
     * @param example   查询条件
     * @param tokenUser 当前用户
     */
    private void addUserCompanyRoleLimit(Example example, TokenUser tokenUser) {
        UserCompanyVO userCompanyVO = childCompanyService.selectByUserId(tokenUser.getUserId(), tokenUser.getSiteId());
        // 非总公司权限 查询条件加入用户管理的公司
        if (!userCompanyVO.getIsAllChildCompany()) {
            List<String> companyIdList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(userCompanyVO.getCompanyIds())) {
                companyIdList = userCompanyVO.getCompanyIds();
            }
            if (!CollectionUtils.isEmpty(userCompanyVO.getGroupIds())) {
                List<GroupCompanyDO> groupCompanyDOList = groupCompanyService
                        .selectByGroupIds(userCompanyVO.getGroupIds(), tokenUser.getSiteId());
                if (!CollectionUtils.isEmpty(groupCompanyDOList)) {
                    companyIdList.addAll(groupCompanyDOList.parallelStream()
                            .map(GroupCompanyDO::getCompanyId).distinct().collect(Collectors.toList()));
                }
            }
            if (!CollectionUtils.isEmpty(companyIdList)) {
                example.and().andIn("id", companyIdList);
            } else {
                example.and().andIsNull("id");
            }
        }
    }

    @Override
    public CompanyDO selectDOById(String companyId, String siteId) {
        return listById(companyId, siteId);
    }

    @Override
    public CompanyDO selectDOByIdNotSite(String companyId) {
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("id", companyId);
        return companyDAO.selectOneByExample(example);
    }

    @Override
    public List<CompanyDO> selectDO(CompanyQuery companyQuery, TokenUser tokenUser) {
        Example example = buildExample(companyQuery, tokenUser.getSiteId());

        // 增加用户公司权限限制
        addUserCompanyRoleLimit(example, tokenUser);

        return companyDAO.selectByExample(example);
    }

    @Override
    public List<CompanyListVO> listVoListByIds(String siteId, String... ids) {
        return getVoListByDoList(listDoByIds(siteId, ids));
    }

    @Override
    public List<CompanyVO> listVoByIds(String siteId, String... ids) {
        List<CompanyDO> companyList = listDoByIds(siteId, ids);
        if (CollectionUtils.isEmpty(companyList)) {
            return null;
        }
        return companyList.stream()
                .map(companyDO -> companyDO.to(CompanyVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public List<CompanyDO> selectBySiteId(String siteId) {
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        return companyDAO.selectByExample(example);
    }

    @Override
    public CompanyDO selectDOByIdNotValid(String companyId, String siteId) {
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("siteId", siteId)
                .andEqualTo("id", companyId);
        List<CompanyDO> companyList = companyDAO.selectByExampleAndRowBounds(example, new RowBounds(0, 1));
        if (!CollectionUtils.isEmpty(companyList)) {
            return companyList.get(0);
        }
        return new CompanyDO();
    }

    @Override
    public CompanyDO selectByName(String companyName, String siteId) {
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("siteId", siteId)
                .andEqualTo("valid", true)
                .andEqualTo("name", companyName);
        List<CompanyDO> companyList = companyDAO.selectByExampleAndRowBounds(example, new RowBounds(0, 1));
        if (!CollectionUtils.isEmpty(companyList)) {
            return companyList.get(0);
        }
        return null;
    }

    @Override
    public List<CompanyDO> selectByNameList(List<String> companyNameList, String siteId) {
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("siteId", siteId)
                .andEqualTo("valid", true)
                .andIn("name", companyNameList);
        return companyDAO.selectByExample(example);
    }

    @Override
    public List<CompanyDO> tileCompanyByUser(TokenUser tokenUser) {
        UserCompanyVO userCompanyVO = childCompanyService.selectByUserId(tokenUser.getUserId(), tokenUser.getSiteId());
        if (userCompanyVO.getIsAllChildCompany()) {
            return selectBySiteId(tokenUser.getSiteId());
        }
        // 拥有的用工单位分组
        List<String> groupIds = userCompanyVO.getGroupIds();
        // 拥有的用工单位(包含拥有分组下的用工单位)
        List<String> userCompanyIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(groupIds)) {
            userCompanyIds = groupCompanyService.selectCompanyIdListByGroupIds(groupIds, tokenUser.getSiteId());
        }
        if (!CollectionUtils.isEmpty(userCompanyVO.getCompanyIds())) {
            userCompanyIds.addAll(userCompanyVO.getCompanyIds());
        }
        return selectByIds(userCompanyIds, tokenUser.getSiteId());
    }

    @Override
    public List<String> tileCompanyIdByUser(TokenUser tokenUser) {
        UserCompanyVO userCompanyVO = childCompanyService.selectByUserId(tokenUser.getUserId(), tokenUser.getSiteId());
        if (userCompanyVO.getIsAllChildCompany()) {
            List<CompanyDO> companyIdList = selectBySiteId(tokenUser.getSiteId());
            return companyIdList.stream().map(CompanyDO::getId).collect(Collectors.toList());
        }
        // 拥有的用工单位分组
        List<String> groupIds = userCompanyVO.getGroupIds();
        // 拥有的用工单位(包含拥有分组下的用工单位)
        List<String> userCompanyIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(groupIds)) {
            userCompanyIds = groupCompanyService.selectCompanyIdListByGroupIds(groupIds, tokenUser.getSiteId());
        }
        if (!CollectionUtils.isEmpty(userCompanyVO.getCompanyIds())) {
            userCompanyIds.addAll(userCompanyVO.getCompanyIds());
        }
        return userCompanyIds;
    }

    @Override
    public List<String> tileCompanyIdByUser2(TokenUser tokenUser) {
        UserCompanyVO userCompanyVO = childCompanyService.selectByUserId(tokenUser.getUserId(), tokenUser.getSiteId());
        if (userCompanyVO.getIsAllChildCompany()) {
            List<String> result = new ArrayList<>();
            result.add("all");
            return result;
        }
        // 拥有的用工单位分组
        List<String> groupIds = userCompanyVO.getGroupIds();
        // 拥有的用工单位(包含拥有分组下的用工单位)
        List<String> userCompanyIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(groupIds)) {
            userCompanyIds = groupCompanyService.selectCompanyIdListByGroupIds(groupIds, tokenUser.getSiteId());
        }
        if (!CollectionUtils.isEmpty(userCompanyVO.getCompanyIds())) {
            userCompanyIds.addAll(userCompanyVO.getCompanyIds());
        }
        return userCompanyIds;
    }

    /**
     * 根据用工单位ID,查询上级分组，直到最后名称，用逗号隔开，类似：用工单位1,分组1-1,分组1，租户A
     * @param firstCompanyId
     * @return
     */
    @Override
    public Map searchCompanyName(String firstCompanyId, TokenUser tokenUser) {
        Map<String,String> map = new HashMap<>();
        Map<String, SiteDO> siteIdDoMap = adminProviderService.selectSiteMap();
        SiteDO siteDO = siteIdDoMap.get(tokenUser.getSiteId());
        String name = siteDO.getName();
        String subjectId = siteDO.getId();
        String subjectType =  "company";
        String parentSubjectId = "";
        String parentSubjectType = "site";

        List<String> list = new ArrayList<>();
        list.add(firstCompanyId);
        List<GroupCompanyDO> groupCompanyList = groupCompanyService.selectByCompanyIds(list, tokenUser.getSiteId());
        if (!CollectionUtils.isEmpty(groupCompanyList)) {
            List<String> groupIds = groupCompanyList.stream().map(GroupCompanyDO::getId).collect(Collectors.toList());
            List<ChildCompanyDO> childCompanyTreee = childCompanyService.groupTree(groupIds, tokenUser.getSiteId());
            if (!CollectionUtils.isEmpty(childCompanyTreee)) {
                String groupName = findGroupName(childCompanyTreee);
                name = name + "," + groupName;
                String groupId = findGroupId(childCompanyTreee);
                subjectId = subjectId + "," + groupId;
                //根据逗号分割的最后一个字段
                parentSubjectType = "group";
                String[] groupIdArr = subjectId.split(",");
                parentSubjectId = groupIdArr[groupIdArr.length-1];
            }
        }
        CompanyDO companyDO = selectDOById(firstCompanyId, tokenUser.getSiteId());
        if (companyDO != null) {
            name = name + "," + companyDO.getName();
            subjectId = subjectId + "," + companyDO.getId();
        }
        map.put("name",name);
        map.put("subjectId",subjectId);
        map.put("subjectType",subjectType);
        map.put("parentSubjectId",parentSubjectId);
        map.put("parentSubjectType",parentSubjectType);
        return map;
    }


    @Override
    public Page<CompanyVO> selectPageNotInGroup(CompanyQuery companyQuery, TokenUser tokenUser) {
        PageHelper.startPage(companyQuery.getPageNo(), companyQuery.getPageSize());
        List<CompanyVO> list = companyDAO.selectPageNotInGroup(tokenUser.getSiteId());
        PageInfo<CompanyVO> pageInfo = new PageInfo<CompanyVO>(list);
        return new Page<>(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), (int) pageInfo.getTotal());
    }

    private String findGroupName(List<ChildCompanyDO> list) {
        ChildCompanyDO childCompanyDO = list.get(0);
        String groupName = childCompanyDO.getName();
        List<ChildCompanyDO> childList = new ArrayList<>();
        List<BaseTreeDO> baseTreeChildList = childCompanyDO.getChildList();
        if (!CollectionUtils.isEmpty(baseTreeChildList)) {
            for (BaseTreeDO baseTreeDO : baseTreeChildList) {
                ChildCompanyDO child = (ChildCompanyDO) baseTreeDO;
                childList.add(child);
            }
            groupName = groupName + "," + findGroupName(childList);
        }
        return groupName;
    }

    private String findGroupId(List<ChildCompanyDO> list) {
        ChildCompanyDO childCompanyDO = list.get(0);
        String groupId = childCompanyDO.getId();
        List<ChildCompanyDO> childList = new ArrayList<>();
        List<BaseTreeDO> baseTreeChildList = childCompanyDO.getChildList();
        if (!CollectionUtils.isEmpty(baseTreeChildList)) {
            for (BaseTreeDO baseTreeDO : baseTreeChildList) {
                ChildCompanyDO child = (ChildCompanyDO) baseTreeDO;
                childList.add(child);
            }
            groupId = groupId + "," + findGroupId(childList);
        }
        return groupId;
    }


    /**
     * 根据公司id获取用工单位
     *
     * @param siteId 站点id
     * @param ids    用工单位id
     * @return 用工单位
     */
    private List<CompanyDO> listDoByIds(String siteId, String... ids) {
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (ids != null && ids.length > 0) {
            example.and().andIn("id", Arrays.asList(ids));
        }
        example.orderBy("gmtCreate").desc();
        return companyDAO.selectByExample(example);
    }

    /**
     * 根据公司名称查询公司
     *
     * @param companyName 公司名称
     * @param tokenUser   当前用户
     * @return 公司
     */
    private List<CompanyDO> selectCompanyByName(String companyName, TokenUser tokenUser) {
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId())
                .andEqualTo("name", companyName);
        return companyDAO.selectByExample(example);
    }


    /**
     * 根据查询参数，构建example
     *
     * @param companyQuery 查询参数
     * @param siteId       所属站点id
     * @return example
     */
    private Example buildExample(CompanyQuery companyQuery, String siteId) {
        Example example = new Example(CompanyDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (!companyQuery.getShowCurrentCompany()) {
            // 不展示当前公司
            ParamException.hasLength(companyQuery.getCurrentCompanyId(), "不展示当前公司id时,请传当前公司id");
            example.and().andNotEqualTo("id", companyQuery.getCurrentCompanyId());
        }
        if (companyQuery.getName() != null) {
            example.and().andLike("name", "%" + companyQuery.getName() + "%");
        }
        if (companyQuery.getIndustry() != null) {
            example.and().andEqualTo("industry", companyQuery.getIndustry());
        }
        if (companyQuery.getLogo() != null) {
            example.and().andEqualTo("logo", companyQuery.getLogo());
        }
        if (companyQuery.getBusinessScope() != null) {
            example.and().andEqualTo("businessScope", companyQuery.getBusinessScope());
        }
        if (companyQuery.getProfile() != null) {
            example.and().andEqualTo("profile", companyQuery.getProfile());
        }
        if (companyQuery.getLegalPerson() != null) {
            example.and().andEqualTo("legalPerson", companyQuery.getLegalPerson());
        }
        if (companyQuery.getAddress() != null) {
            example.and().andEqualTo("address", companyQuery.getAddress());
        }
        if (companyQuery.getPersonSize() != null) {
            example.and().andEqualTo("personSize", companyQuery.getPersonSize());
        }
        if (companyQuery.getOfficialWebsite() != null) {
            example.and().andEqualTo("officialWebsite", companyQuery.getOfficialWebsite());
        }
        if (companyQuery.getTelephone() != null) {
            example.and().andEqualTo("telephone", companyQuery.getTelephone());
        }
        if (companyQuery.getEmail() != null) {
            example.and().andEqualTo("email", companyQuery.getEmail());
        }
        if (companyQuery.getDepId() != null) {
            example.and().andEqualTo("depId", companyQuery.getDepId());
        }
        // 排序
        ExampleKit.setExampleOrder(example, companyQuery.getOrders());
        return example;
    }
}




